#pragma once
#include "stdafx.h"

template <class T> class My_vector
{
	vector<T> Vector;
	T begin_val{};
	T end_val{};

public:
	My_vector() = default;
	My_vector(const T& begin, const T& end) :begin_val{ begin }, end_val{ end }{}
	My_vector(const T&, const T&, initializer_list<T>);

	My_vector(const My_vector<T>& other);//����� �� ���������
	My_vector(My_vector<T>&& other);//����� �� ���������

	~My_vector() = default;

	int Size() { return Vector.size(); }

	My_vector<T>& operator=(const My_vector<T>& other) = default;
	My_vector<T>& operator=(initializer_list<T>);
	My_vector<T>& operator=(My_vector<T>&& other) = default;

	My_vector<T>& back_insert(initializer_list<T>);
	My_vector<T>& erase_if(initializer_list<T>);


	void Sort(char x = '<');
	void print_container();


	void change_begin_range(const T& begin) { begin_val = begin; standardization(*this); }
	void change_end_range(const T& end) { end_val = end; standardization(*this); }
	void change_range(const T& begin, const T& end)
	{
		begin_val = begin; end_val = end; standardization(*this);
	}
	void standardization(My_vector<T>& This);
	bool normalization(const T& val);
};


template<class T>
inline My_vector<T>::My_vector(const T& begin, const T& end, initializer_list<T> l)
	:begin_val{ begin }, end_val{ end }
{
	for (auto& val : l)
	{
		if (val >= begin_val && val <= end_val)
		{
			if (std::find(Vector.begin(), Vector.end(), val) == Vector.end())
			{
				*back_inserter(Vector) = val;//����������� ��� �������� �� �����
			}
		}
	}
}


template<class T>
inline My_vector<T>::My_vector(const My_vector<T>& other)
	:begin_val{ other.begin_val }, end_val{ other.end_val }/*, Vector{ other.Vector}*/
{
	if (&other != this)
	{
		Vector.resize(other.Vector.size());
		std::copy(other.Vector.begin(), other.Vector.end(), Vector.begin());//����� ������������ operator=
	}
}


template<class T>
inline My_vector<T>::My_vector(My_vector<T>&& other)
	:begin_val{ std::move(other.begin_val) }, end_val{ std::move(other.end_val)}
{
	if (&other != this)//�� ����� � ������������� �����������
	{
		Vector = std::move(other.Vector);
	}
}


//template<class T>
//My_vector<T>& My_vector<T>::operator=(const My_vector<T>& other)
//{
//	if (&other != this)
//	{
//		begin_val=other.begin_val;
//		end_val= other.end_val;
//
//		Vector.resize(other.Vector.size());
//		std::copy(other.Vector.begin(), other.Vector.end(), Vector.begin());
//	}
//	return *this;
//}


template<class T>
My_vector<T>& My_vector<T>::operator=(/*const */initializer_list<T> l)
{
	if (!Vector.empty())Vector.clear();
	return this->back_insert(l);
}


//template<class T>
//My_vector<T>& My_vector<T>::operator=(My_vector<T>&& other)
//{
//	if (&other != this)
//	{
//		begin_val=other.begin_val;
//		end_val=other.end_val ;
//		Vector = std::move(other.Vector);
//	}
//	return *this;
//}


template<class T>
inline My_vector<T>& My_vector<T>::back_insert(initializer_list<T> l)
{
	copy_if(begin(l), end(l), back_inserter(Vector), [&](auto& x) {return x >= begin_val && x <= end_val && normalization(x); });
	return *this;
}


template<class T>
inline My_vector<T>& My_vector<T>::erase_if(initializer_list<T> l)
{
	auto l1 = [&](auto& val)
	{ bool fl = false;
	for (auto& x : l)
	{
		if (x == val) { fl = true; break; }
	}
	return fl; };

	auto it = remove_if(Vector.begin(), Vector.end(), l1);
	Vector.erase(it, Vector.end());
	return *this;
}


template<class T>
inline void My_vector<T>::standardization(My_vector<T>& This)
{
	std::list<T>l;
	std::copy(Vector.begin(), Vector.end(), std::back_inserter(l));
	l.remove_if([this](const auto& val) {return (val < begin_val || val > end_val); });
	Vector.assign(l.begin(), l.end());
}

template<class T>
bool My_vector<T>::normalization(const T& val)
{
	return find(Vector.begin(), Vector.end(), val) == Vector.end();
}


template<class T>
inline void My_vector<T>::print_container()
{
	for (size_t i = 0; i < Vector.size(); i++)
	{
		std::cout << Vector[i] << " ";
	}
	std::cout << std::endl;
}

template<class T>
inline void My_vector<T>::Sort(char x)
{	
	if (x == '>') 
	{
	sort(Vector.begin(), Vector.end(), [](const auto& x, const auto& y) { return x > y; });
	return;
	}

	sort(Vector.begin(), Vector.end(), [](const auto& x, const auto& y) { return x < y; });
}
